/*
 * AutoAnswer
 * Copyright (C) 2010 EverySoft
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * This file incorporates work covered by the following copyright and
 * permission notice:
 *
 *   Copyright (C) 2010 Tedd Scofield
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

package com.everysoft.autoanswer;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Date;

import com.android.internal.telephony.ITelephony;

import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioRecord.OnRecordPositionUpdateListener;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.telephony.TelephonyManager;
import android.view.KeyEvent;

public class AutoAnswerIntentService extends IntentService {
	private static final int REQUEST_CODE_RECORDING = 100;

	public AutoAnswerIntentService() {
		super("AutoAnswerIntentService");
	}

	@Override
	protected void onHandleIntent(Intent intent) {
		Context context = getBaseContext();

		// Load preferences
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);

		// Answer the phone
		answerPhoneHeadsethook(context);

		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			// We don't really care
		}
		// Make sure the phone is on call
		TelephonyManager tm = (TelephonyManager) context
				.getSystemService(Context.TELEPHONY_SERVICE);
		if (tm.getCallState() != TelephonyManager.CALL_STATE_OFFHOOK) {
			return;
		}
		// Enable the speakerphone
		AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
		audioManager.setSpeakerphoneOn(true);
		// audioManager.setRouting(AudioManager.MODE_CURRENT,
		// AudioManager.ROUTE_SPEAKER, AudioManager.ROUTE_ALL);
		audioManager.setMode(AudioManager.MODE_CURRENT);

		// UnMute the call
		audioManager.setMicrophoneMute(false);

		playGreetingAudio(context);
		// Mute the call
		audioManager.setMicrophoneMute(true);

		startRecording(tm, intent);
		while (tm.getCallState() == TelephonyManager.CALL_STATE_OFFHOOK) {
			System.out.println("Still recording");
		}
		stopRecording();
		return;
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		stopRecording();
	}

	private void playGreetingAudio(Context context) {
		MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.greeting_audio_file);
		mediaPlayer.setVolume(100, 100);
		mediaPlayer.start();
		while (mediaPlayer.isPlaying()) {
			System.out.println("still playing");
		}
	}

	private void startRecording(TelephonyManager tm, Intent intent) {
		int state = tm.getCallState();
		String incnum = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
		int day = new Date().getDate(), mont = new Date().getMonth(), yea = new Date().getYear(), hou = new Date()
				.getHours(), min = new Date().getMinutes();
		String audioFile = "" + day + "_" + mont + "_" + yea + "_" + hou + "_" + min + "_" + incnum
				+ ".3gp";
		if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
			String mFileName = Environment.getExternalStorageDirectory().getAbsolutePath() + "/"
					+ audioFile;
			mRecorder = new MediaRecorder();
			mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
			mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
			mRecorder.setOutputFile(mFileName);
			mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

			try {
				mRecorder.prepare();
			} catch (IOException e) {
				e.printStackTrace();
			}

			mRecorder.start();
		}

	}

	public static void stopRecording() {
		if (mRecorder != null) {
			mRecorder.stop();
			mRecorder.release();
			mRecorder = null;
		}
	}

	private void startRecording_old(TelephonyManager tm, Intent intent) {
		int state = tm.getCallState();
		if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
			final int sampleRate = 44100;
			int bufferSize = AudioRecord.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_IN_MONO,
					AudioFormat.ENCODING_PCM_16BIT);

			// aim for 1 second
			int detectAfterEvery = (int) (sampleRate * 1.0f);

			if (detectAfterEvery > bufferSize) {
				bufferSize = detectAfterEvery;
			}

			AudioRecord recorder = new AudioRecord(
					MediaRecorder.AudioSource.VOICE_DOWNLINK
							| MediaRecorder.AudioSource.VOICE_UPLINK
							| MediaRecorder.AudioSource.VOICE_CALL, sampleRate,
					AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
			recorder.setPositionNotificationPeriod(detectAfterEvery);

			final short[] audioData = new short[bufferSize];
			final int finalBufferSize = bufferSize;

			OnRecordPositionUpdateListener positionUpdater = new OnRecordPositionUpdateListener() {
				@Override
				public void onPeriodicNotification(AudioRecord recorder) {
					Date d = new Date();
					// it should be every 1 second, but it is actually,
					// "about every 1 second"
					// like 1073, 919, 1001, 1185, 1204 milliseconds of time.
					recorder.read(audioData, 0, finalBufferSize);

					// do something amazing with audio data
				}

				@Override
				public void onMarkerReached(AudioRecord recorder) {

				}

			};
			recorder.setRecordPositionUpdateListener(positionUpdater);

			recorder.startRecording();
			while (state == TelephonyManager.CALL_STATE_OFFHOOK) {
				recorder.read(audioData, 0, bufferSize);
			}
		}

	}

	MediaRecorder _recorder = new MediaRecorder();
	private static MediaRecorder mRecorder;

	public void start() throws IOException {
		try {
			String state = android.os.Environment.getExternalStorageState();
			if (!state.equals(android.os.Environment.MEDIA_MOUNTED)) {
				throw new IOException("SD Card is not mounted.  It is " + state + ".");
			}
			// String incnum =
			// intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);

			// int day = new Date().getDate(), mont = new Date().getMonth(), yea
			// = new Date()
			// .getYear(), hou = new Date().getHours(), min = new
			// Date().getMinutes();
			// String s = "" + day + "_" + mont + "_" + yea + "_" + hou + "_" +
			// min + "_" + incnum
			// + "_Incoming" + ".3gp";

			// make sure the directory we plan to store the recording in exists
			File directory = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
					+ "/sam.wav").getParentFile();
			if (!directory.exists() && !directory.mkdirs()) {
				throw new IOException("Path to file could not be created.");
			}

			_recorder
					.setAudioSource(MediaRecorder.AudioSource.VOICE_DOWNLINK
							| MediaRecorder.AudioSource.VOICE_UPLINK
							| MediaRecorder.AudioSource.VOICE_CALL);
			_recorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
			_recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
			// setOutputFile(Environment.getExternalStorageDirectory().getAbsolutePath()
			// + "/test.wav");
			_recorder.prepare();
			_recorder.start();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void answerPhoneHeadsethook(Context context) {
		// Simulate a press of the headset button to pick up the call
		Intent buttonDown = new Intent(Intent.ACTION_MEDIA_BUTTON);
		buttonDown.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN,
				KeyEvent.KEYCODE_HEADSETHOOK));
		context.sendOrderedBroadcast(buttonDown, "android.permission.CALL_PRIVILEGED");

		// froyo and beyond trigger on buttonUp instead of buttonDown
		Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON);
		buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP,
				KeyEvent.KEYCODE_HEADSETHOOK));
		context.sendOrderedBroadcast(buttonUp, "android.permission.CALL_PRIVILEGED");
	}

	private void endPhoneCall(Context context) {
		// Simulate a press of the headset button to end up the call
		Intent buttonDown = new Intent(Intent.ACTION_MEDIA_BUTTON);
		buttonDown.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN,
				KeyEvent.KEYCODE_ENDCALL));
		context.sendOrderedBroadcast(buttonDown, "android.permission.CALL_PRIVILEGED");

		// froyo and beyond trigger on buttonUp instead of buttonDown
		Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON);
		buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP,
				KeyEvent.KEYCODE_ENDCALL));
		context.sendOrderedBroadcast(buttonUp, "android.permission.CALL_PRIVILEGED");
	}

	@SuppressWarnings("unchecked")
	private void answerPhoneAidl(Context context) throws Exception {
		// Set up communication with the telephony service (thanks to Tedd's
		// Droid Tools!)
		TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
		Class c = Class.forName(tm.getClass().getName());
		Method m = c.getDeclaredMethod("getITelephony");
		m.setAccessible(true);
		ITelephony telephonyService;
		telephonyService = (ITelephony) m.invoke(tm);

		// Silence the ringer and answer the call!
		telephonyService.silenceRinger();
		telephonyService.answerRingingCall();
	}
}
